package com.flute.framework.autoprompt;

import com.flute.framework.monitor.DataRecordLogger;
import com.flute.framework.monitor.EventLogger;
import com.flute.tools.data.DataIterator;
import com.flute.tools.data.DataRecord;
import com.flute.tools.timer.FlexTimer;

public class AutoPromptMantian {

	private ITokenDataProvider provider;
	private int updateInterval;
	private ITrainningTokenBuilder builder;
	private volatile boolean initializing;
	private volatile boolean running;

	public ITrainningTokenBuilder getBuilder() {
		return builder;
	}

	public void setBuilder(ITrainningTokenBuilder builder) {
		this.builder = builder;
	}

	public AutoPromptMantian() {
	}

	public int getUpdateInterval() {
		return updateInterval;
	}

	public void setUpdateInterval(int updateInterval) {
		this.updateInterval = updateInterval;
	}

	public void start() {
		if (!running) {
			initializing = true;
			running = true;
			initial();
			if (updateInterval == 0) {
				updateInterval = 100000;
			}
			FlexTimer.getInstance().startTimer("update-prompt", this, "update",
					updateInterval, true);
		}
	}

	public ITokenDataProvider getProvider() {
		return provider;
	}

	public void setProvider(ITokenDataProvider provider) {
		this.provider = provider;
	}

	public void update() throws InterruptedException {
		long id = EventLogger.startNewEvent(AutoPromptMonitor.getUpdateKey());
		DataRecordLogger dataLogger = DataRecordLogger.getLogger(EventLogger
				.getCurrentEventId(AutoPromptMonitor.getUpdateKey()));

		while (initializing) {
			EventLogger
					.info("正在初始化，等待10s...", AutoPromptMonitor.getUpdateKey());
			Thread.sleep(10000);
		}

		EventLogger.info("开始更新自动提示...", AutoPromptMonitor.getUpdateKey());
		checkWriting();
		provider.beginUpdate();

		// 处理添加
		EventLogger.info("开始'add'自动提示的数据...", AutoPromptMonitor.getUpdateKey());
		DataIterator<TokenData> addIt = provider.getAddTokenDatas();
		int count = 0;
		try{
			while (addIt.hasNext()) {
				TokenData td = addIt.next();

				DataRecord dr = td.toDataRecord();
				dr.AddField("action", "add");
				dataLogger.recordInfo(dr);
				count++;

				AutoPrompt.getInstance().train(td, builder);
			}	
			EventLogger.info("'add'自动提示结束,'add'条数为'" + count + "'.",
					AutoPromptMonitor.getUpdateKey());
		}finally {
			addIt.close();	
		}

		DataIterator<TokenData> initialIt = provider.getInitialTokenDatas();

		// 处理更新
		EventLogger.info("开始'update'自动提示的数据...", AutoPromptMonitor
				.getUpdateKey());
		DataIterator<TokenData> updateIt = provider.getUpdateTokenDatas();
		count = 0;
		while (updateIt.hasNext()) {
			DataRecord dr = updateIt.next().toDataRecord();
			dr.AddField("action", "update");
			dataLogger.recordInfo(dr);
			count++;
		}
		updateIt.reset();
		AutoPrompt.getInstance().update(updateIt, builder, initialIt);
		updateIt.close();
		EventLogger.info("'update'自动提示结束,'update'条数为'" + count + "'.",
				AutoPromptMonitor.getUpdateKey());

		initialIt.reset();

		// 处理删除
		EventLogger.info("开始'delete'自动提示的数据...", AutoPromptMonitor
				.getUpdateKey());
		DataIterator<TokenData> deleteIt = provider.getDeleteTokenDatas();
		count = 0;
		while (deleteIt.hasNext()) {
			DataRecord dr = deleteIt.next().toDataRecord();
			dr.AddField("action", "delete");
			dataLogger.recordInfo(dr);
			count++;
		}
		deleteIt.reset();
		AutoPrompt.getInstance().delete(deleteIt, builder, initialIt);
		deleteIt.close();
		EventLogger.info("'delete'自动提示结束,'delete'条数为'" + count + "'.",
				AutoPromptMonitor.getUpdateKey());

		initialIt.close();

		provider.endUpdate();
		EventLogger.info("自动提示的更新过程结束.", AutoPromptMonitor.getUpdateKey());
		EventLogger.endEvent(id);
	}

	private void checkWriting() {
		while (provider.isWriting()) {
			EventLogger.info("自动提示数据正在写入，等待5秒...", AutoPromptMonitor
					.getUpdateKey());
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void initial() {
		EventLogger.startNewEvent(AutoPromptMonitor.getInitialKey());
		checkWriting();
		Thread th = new Thread(getRunnable());
		th.start();
	}

	private Runnable getRunnable() {
		return new Runnable() {

			@Override
			public void run() {
				EventLogger.info("自动提示开始初始化...", AutoPromptMonitor
						.getInitialKey());
				provider.beginInital();
				DataIterator<TokenData> it = provider.getInitialTokenDatas();

				int count = 0;
				try{
					ITrainningTokenBuilder builder = new DefaultTrainingTokenBuilder();
					while (it.hasNext()) {
						TokenData token = it.next();
						if (count++ % 10000 == 0) {
							EventLogger.info("train:" + count, AutoPromptMonitor
									.getInitialKey());
						}
						if (token != null) {
							AutoPrompt.getInstance().train(token, builder);
						}
					}
					EventLogger.info("train done, count:" + count,
							AutoPromptMonitor.getInitialKey());	
				}finally{
					it.close();	
				}
				provider.endInitial();

				EventLogger
						.info("自动提示初始化结束", AutoPromptMonitor.getInitialKey());
				EventLogger.endEvent(EventLogger.getCurrentEventId(AutoPromptMonitor.getInitialKey()));
				initializing = false;
			}

		};
	}
}
